home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / cli / okami15.lzh / OKAMI15 / SOURCE / MSH.C < prev   
C/C++ Source or Header  |  1992-09-20  |  10KB  |  457 lines

  1. /********************************************************************
  2.  
  3.          Mikro-Shell: Startprogramm fuer Okami-Shell
  4.  
  5.  
  6.  
  7.           von Wolfram Rösler 1.11.89
  8.  
  9.         Usenet: wr@bara.oche.de
  10.         Mausnetz: Wolfram Roesler @ AC2
  11.  
  12.             ~~~ FREEWARE ~~~
  13.  
  14.  
  15.   Änderungen:
  16.   
  17. 18.02.90 Optional Übergabe der Konfigurationsdatei
  18. 01.03.90 Internes Kommando: echo
  19. 31.03.90 Übergabe mehrerer Konfigurationsdateien
  20.      internes Kommando: incl
  21. 10.05.90 Länge des Para-Strings in Pexec korrekt
  22.      Zeilenumbruch mit \ am Ende einer Zeile
  23. 28.12.90 Kommandozeile mit -c und Kommandos
  24.      internes Kommando: ver
  25. 05.03.91 interne Kommandos exit und wait
  26. 19.06.91 1.4: Steuersequenzen in echo
  27. 19.10.91 1.5: Anpassung an Ansi-C (PureC), Option -v für Versionsnummer
  28. 28.01.92 1.6: Kommando "exec", MiNT-Unterstützung
  29. 20.08.92      wait-Bug korrigiert
  30. 30.08.92 1.7: neues Kommando "cd"
  31.  
  32. *******************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <time.h>
  39. #include <tos.h>
  40.  
  41. /* Das folgende auf 1 setzen, wenn Mint unterstützt werden soll:
  42. ** (der einzige Grund, es nicht auf 1 zu setzen, ist daß man
  43. ** kein mintbind.h hat)
  44. */
  45. #define USEMINT 1
  46.  
  47. #if USEMINT
  48. #include <mintbind.h>
  49. #endif
  50.  
  51. #define strlast(S)    (*(S+strlen(S)-1))    /* String: letztes char.*/
  52.  
  53. /* Strings mit Programmname und Versionsnummer                */
  54.  
  55. #define TPName        "Okami Microshell"
  56. #define TPVersion    "1.7"
  57.  
  58. /* Weitere globale Variablen und defines */
  59.  
  60. const char KONFFILE[]=    "msh.inf";    /* Default bei argc==1        */
  61. #define CMDLEN        (3*80)
  62. #define ARGV0        "msh"        /* eigentlich: argv[0]        */
  63. #define EXITCODE    (-999)        /* Script beenden        */
  64.  
  65. int MsgFlag=1;                /* Flag für Meldungen        */
  66. int MintThere=0;            /* Flag: Mint ist installiert    */
  67.  
  68. /* Prototypen */
  69. int    msh    (char FName[]);
  70. int    DoCom    (char *Para);
  71. void    Xputs    (register char *s);
  72. void    DoExec    (char *Cmd);
  73. int    DoWait    (char *Para);
  74.  
  75. /************************************************************************/
  76.  
  77. int main(int argc,char *argv[])
  78. {
  79.   register int i;
  80.   short ExFlag=0;            /* 0: Script, 1: Kommando    */
  81.   int Erg;
  82.   int DoFlag=0;
  83.  
  84. #if USEMINT
  85.   /* Herausfinden, ob Mint intalliert ist. Das geht durch Durchsuchen
  86.   ** des Cookiejars nach dem MiNT-Eintrag.
  87.   */
  88.   {
  89.     register struct C {long tag,val;} *c;
  90.     long s;
  91.  
  92.     s = Super(0L);
  93.     c = *(struct C**)0x5a0;
  94.     Super((void*)s);
  95.  
  96.     if (c)
  97.       for(;c->tag;c++)
  98.         if (c->tag == 'MiNT')
  99.         {
  100.           MintThere = 1;
  101.           break;
  102.         }
  103.   }
  104. #endif
  105.   
  106.   if (argc>1)
  107.   {
  108.     if (argc==2 && !strcmp(argv[1],"-v"))
  109.     {
  110.       DoCom("ver");
  111.       return 0;
  112.     }
  113.     for (i=1;i<argc;i++)
  114.     {
  115.       if (argv[i][0]=='\0')    /* ja, das _kommt_ vor */
  116.         continue;
  117.  
  118.       if (!strcmp(argv[i],"-c"))
  119.       {
  120.     ExFlag=1;
  121.     continue;
  122.       }
  123.       if (ExFlag)
  124.     Erg=DoCom(argv[i]);
  125.       else 
  126.     Erg=msh(argv[i]);
  127.       DoFlag=1;
  128.     }
  129.   }
  130.  
  131.   if (!DoFlag)
  132.     Erg=msh(KONFFILE);
  133.  
  134.   return Erg;
  135. }
  136.  
  137. /************************************************************************
  138.  
  139.     msh: ein MSH-Script ausführen
  140.  
  141. ************************************************************************/
  142. int msh(char FName[])
  143. {
  144.   FILE *FPtr;                /* File-Ptr. Konf.datei     */
  145.   char    St[CMDLEN+1];            /* eingelesene Zeile        */
  146.   char    Para2[CMDLEN+1];        /* Hilfsstring            */
  147.   register char *Para;
  148.   char c;
  149.   int Erg;
  150.   
  151.   while (isspace(*FName)) FName++;
  152.  
  153.   if ((FPtr=fopen(FName,"r"))==NULL)
  154.   {
  155.     fputs(ARGV0,stdout);
  156.     fputs(": cannot open ",stdout);
  157.     puts(FName);
  158.      return -1;
  159.   }
  160.  
  161.   while (fgets(St,3*80,FPtr)!=NULL)
  162.   {
  163.     Para=St;
  164.  
  165.     while (isspace(*Para)) Para++;    /* führende Leerzeichen          */
  166.  
  167.     if (*Para=='\0' || *Para=='\n' || *Para=='#')
  168.       continue;
  169.  
  170.     for (;;)                /* endende Leerzeichen        */
  171.     {
  172.       c=strlast(Para);
  173.       if (isspace(c))
  174.     strlast(Para)='\0';
  175.       else
  176.     break;
  177.     }
  178.     
  179.     while(strlast(Para)=='\\')        /* \ am Ende: Zeilenumbruch    */
  180.     {
  181.       strlast(Para)='\0';
  182.       fgets(Para2,80,FPtr);
  183.       while (Para2[strlen(Para2)-1]=='\n')
  184.     Para2[strlen(Para2)-1]='\0';
  185.       strcat(Para,Para2);
  186.     }
  187.  
  188.     /* Kommando ausführen */
  189.  
  190.     Erg=DoCom(St);
  191.     if (Erg==EXITCODE)
  192.       break;    /* Script beenden */
  193.   }
  194.  
  195.   fclose(FPtr);
  196.   return Erg;
  197. }
  198.  
  199. /************************************************************************
  200.  
  201.     DoCom: ein MSH-Kommando ausführen
  202.  
  203. Return: EXITCODE: aktuelles Script beenden
  204.     sonst: Returncode
  205. ************************************************************************/
  206. int DoCom(char *Para)
  207. {
  208.   char    *Com;
  209.   char Para2[CMDLEN+1];            /* Hilfsstring            */
  210.   int Ret=0;                /* Rückgabewert            */
  211.  
  212.   if (Para[0]=='-')            /* -: Meldung abschalten    */
  213.   {
  214.     MsgFlag=0;
  215.     return 0;
  216.   }
  217.   if (Para[0]=='+')            /* +: Meldung einschalten    */
  218.   {
  219.     MsgFlag=1;
  220.     return 0;
  221.   }
  222.  
  223.   for (Com=Para;*Para && !isspace(*Para);Para++);
  224.   if (*Para!='\0')
  225.     *Para++='\0';
  226.  
  227.   if (!strcmp(Com,"cd"))            /* internes Kommando: cd    */
  228.   {
  229.     char *Dir = Para;
  230.     if (Dir[1]==':')
  231.     {
  232.       Dsetdrv(toupper(Dir[0])-'A');
  233.       Dir+=2;
  234.     }
  235.     if (Dsetpath(Dir)!=0)
  236.       printf("cannot cd to %s\n",Para);
  237.   }
  238.    
  239.   else if (!strcmp(Com,"echo"))        /* internes Kommando: echo    */
  240.     Xputs(Para);
  241.  
  242.   else if (!strcmp(Com,"exit"))        /* internes Kommando: exit    */
  243.     return EXITCODE;
  244.       
  245.   else if (!strcmp(Com,"incl"))        /* internes Kommando: incl    */
  246.     msh(Para);
  247.  
  248.   else if (!strcmp(Com,"exec"))        /* internes Kommando: exec    */
  249.     DoExec(Para);
  250.  
  251.   else if (!strcmp(Com,"ver"))        /* internes Kommando: ver    */
  252.   {
  253.     puts(TPName " " TPVersion);
  254.     puts("compiled " __DATE__ " " __TIME__);
  255.   }
  256.  
  257.   else if (!strcmp(Com,"wait"))        /* internes Kommando: wait    */
  258.     Ret = DoWait(Para);
  259.     
  260.   else                /* Programm starten */
  261.   {
  262.     /* Kommentarmodus: Kommando ausgeben */
  263.     if (MsgFlag)
  264.     {
  265.       fputs(Com,stdout);
  266.       fputc(' ',stdout);
  267.       puts(Para);
  268.     }
  269.     
  270.     Para2[0]=(char)strlen(Para);
  271.     strcpy(Para2+1,Para);
  272.     if ((Ret=(int)Pexec(0,Com,Para2,0L))<0)
  273.     if (MsgFlag)
  274.     {
  275.       fputs(Com,stdout);
  276.       puts(": not found");
  277.     }
  278.   }
  279.  
  280.   return Ret;
  281. }
  282.  
  283.  
  284. /************************************************************************
  285.  
  286.     Xputs: wie puts, aber interpretiert Escape-Sequenzen mit \ und ^
  287.  
  288. ************************************************************************/
  289. void Xputs(register char *s)
  290. {
  291.   for(;*s;s++)
  292.   {
  293.     switch(*s)
  294.     {
  295.       case '\\':
  296.         s++;
  297.         switch(*s)
  298.     {
  299.       case '\0':
  300.         return;
  301.       case 'n':
  302.         fputc('\n',stdout);
  303.         break;
  304.       case 't':
  305.         fputc('\t',stdout);
  306.         break;
  307.       case 'b':
  308.         fputc('\b',stdout);
  309.         break;
  310.       case 'c':
  311.         break;
  312.       default:
  313.         fputc(*s,stdout);
  314.     }
  315.     break;
  316.       case '^':
  317.         s++;
  318.     switch(*s)
  319.     {
  320.       case '\0':
  321.         return;
  322.       default:
  323.         fputc(*s-'A'+1,stdout);
  324.     }
  325.         break;
  326.       default:
  327.         fputc(*s,stdout);
  328.     }
  329.   }
  330.  
  331.   if (!(s[-1]=='c' && s[-2]=='\\'))
  332.     fputc('\n',stdout);
  333. }
  334.  
  335. /************************************************************************
  336.  
  337.     DoExec: das interne Kommando exec
  338.     Pexec und dann exit. Hat natürlich nur Sinn mit MiNT.
  339.  
  340. *************************************************************************/
  341. void DoExec(char *Cmd)
  342. {
  343.   char *Arg;
  344.   char S[130];
  345.   int Mode = MintThere ? 200 : 0;
  346.  
  347.   while(isspace(*Cmd)) Cmd++;
  348.  
  349.   if (MsgFlag)
  350.     puts(Cmd);
  351.  
  352.   for(Arg=Cmd;*Arg && !isspace(*Arg);Arg++);
  353.   if (*Arg)
  354.     *Arg++='\0';
  355.  
  356.   strncpy(S+1,Arg,128);
  357.   S[0] = (char)strlen(Arg);
  358.  
  359.   if (Pexec(Mode,Cmd,S,0L)<0)
  360.   {
  361.     fputs(Cmd,stdout);
  362.     puts(": not found");
  363.   }
  364.   else
  365.     exit(0);
  366.   return;
  367. }
  368.  
  369. /************************************************************************
  370.  
  371.     DoWait: das interne Kommando wait
  372.  
  373.     Syntax: wait ((ttmmmjj|*) HHMMSS|key)
  374.  
  375. Return: EXITCODE: User hat abgebrochen, sonst: Zeit ist erreicht
  376.  
  377. *************************************************************************/
  378. int DoWait(char